﻿
namespace TestSapco
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using SAP.Middleware.Connector;
    using System.Data;
    using System.Configuration;
    using System.Data.SqlClient;

    public class SapDestinationConfiguration : IDestinationConfiguration
    {
        public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;

        public bool ChangeEventsSupported()
        {
            return false;
        }

        public string Decrypt(string base64Hash)
        {
            byte[] codeBytes = Convert.FromBase64String(base64Hash);
            return System.Text.Encoding.UTF8.GetString(codeBytes);
        }


        public RfcConfigParameters GetParameters(string destinationName)
        {
            RfcConfigParameters rfcConfigParameters = null;

            if (!string.IsNullOrEmpty(destinationName))
            {
                rfcConfigParameters = new RfcConfigParameters();

                rfcConfigParameters.Add("USER", Decrypt(ConfigurationManager.AppSettings["SAP_USER"]));
                rfcConfigParameters.Add("PASSWD", Decrypt(ConfigurationManager.AppSettings["SAP_PASSWD"]));


                rfcConfigParameters.Add("ASHOST", ConfigurationManager.AppSettings["SAP_ASHOST"]);
                rfcConfigParameters.Add("SYSNR", ConfigurationManager.AppSettings["SAP_SYSNR"]);
                rfcConfigParameters.Add("CLIENT", ConfigurationManager.AppSettings["SAP_CLIENT"]);

                rfcConfigParameters.Add("LANG", ConfigurationManager.AppSettings["SAP_LANG"]);
                rfcConfigParameters.Add("POOL_SIZE", ConfigurationManager.AppSettings["SAP_POOL_SIZE"]);
                rfcConfigParameters.Add("IDLE_TIMEOUT", ConfigurationManager.AppSettings["SAP_IDLE_TIMEOUT"]);
            }

            return rfcConfigParameters;
        }
    }

    public class SAPB2E
    {
        RfcDestination rfcDestination = null;


        public SAPB2E()
        {
            if (!RfcDestinationManager.IsDestinationConfigurationRegistered())
            {
                RfcDestinationManager.RegisterDestinationConfiguration(new SapDestinationConfiguration());
            }

            this.rfcDestination = RfcDestinationManager.GetDestination("SAP");
        }


        #region Helper functions 
        
        /// <summary>
        /// Find the first TABLE found from RfcFunction.
        /// Cast the result from the function into a DataTable.
        /// </summary>
        /// <param name="f">A RfcFunction</param>
        /// <returns>DataTable</returns>
        public DataTable GetDataTable(IRfcFunction f)
        {
            // Function:
            // Returns the first TABLE type in RfcFunction
            DataTable dt = null;

            for (int i = 0; i < f.ElementCount; i++)
            {
                RfcElementMetadata metadata = f.GetElementMetadata(i);
                if (metadata.DataType == RfcDataType.TABLE)
                {
                    RfcStructureMetadata tableMetadata = metadata.ValueMetadataAsTableMetadata.LineType;

                    // Define structure of datatable based on tableMetadata
                    dt = new DataTable(tableMetadata.Name);
                    for (int fieldIndex = 0; fieldIndex < tableMetadata.FieldCount; fieldIndex++)
                    {
                        RfcFieldMetadata fieldMetadata = tableMetadata[fieldIndex];
                        switch (fieldMetadata.DataType)
                        {
                            case RfcDataType.CHAR:
                                //dt.Columns.Add(fieldMetadata.Name, typeof(string));
                                dt.Columns.Add(fieldMetadata.Name, typeof(string));
                                break;
                            default:
                                dt.Columns.Add(fieldMetadata.Name); // Note: default datatype is string
                                break;
                        }
                    }

                    // Write into dataTable
                    IRfcTable tbl = f.GetTable(i);
                    for (int rowIndex = 0; rowIndex < tbl.RowCount; rowIndex++)
                    {
                        DataRow newRow = dt.NewRow();
                        for (int columnIndex = 0; columnIndex < dt.Columns.Count; columnIndex++)
                        {
                            newRow[columnIndex] = tbl[rowIndex].GetValue(columnIndex);
                        }

                        dt.Rows.Add(newRow);
                    }

                    break;
                }
            }

            return dt;
        }
        
        public DataTable GetSapDataTable(IRfcFunction f, string codeTypeId)
        {
            // Function:
            // Returns the first TABLE type in RfcFunction
            DataTable dt = null;


            for (int i = 0; i < f.ElementCount; i++)
            {
                RfcElementMetadata metadata = f.GetElementMetadata(i);
                if (metadata.DataType == RfcDataType.TABLE)
                {
                    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SRM"].ConnectionString))
                    {
                        SqlCommand cmd = conn.CreateCommand();
                        SqlDataAdapter da = new SqlDataAdapter(cmd);
                        cmd.CommandText = "SELECT TOP 1 * FROM SAP_Code WHERE CodeTypeId IS NULL;";
                        DataSet ds = new DataSet();
                        da.Fill(ds);
                        dt = ds.Tables[0];
                    }

                    // Write into dataTable
                    IRfcTable tbl = f.GetTable(i);
                    for (int rowIndex = 0; rowIndex < tbl.RowCount; rowIndex++)
                    {
                        DataRow newRow = dt.NewRow();
                        newRow["CodeTypeId"] = codeTypeId;
                        newRow["Id"] = tbl[rowIndex].GetValue(0);
                        newRow["DisplayText"] = tbl[rowIndex].GetValue(1);
                        newRow["DisplaySequence"] = (rowIndex + 1);
                        //newRow["ParentId1"] = tbl[rowIndex].GetValue(1);
                        //newRow["ParentId2"] = tbl[rowIndex].GetValue(1);
                        dt.Rows.Add(newRow);
                    }

                    break;
                } // if (metadata.DataType == RfcDataType.TABLE)
            } // for (int i = 0; i < f.ElementCount; i++)

            return dt;
        }

        public DataTable GetSapDataTable(IRfcFunction f, string codeTypeId, bool hasParentId1, bool hasParentId2)
        {
            // Function:
            // Returns the first TABLE type in RfcFunction
            DataTable dt = null;


            for (int i = 0; i < f.ElementCount; i++)
            {
                RfcElementMetadata metadata = f.GetElementMetadata(i);
                if (metadata.DataType == RfcDataType.TABLE)
                {
                    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SRM"].ConnectionString))
                    {
                        SqlCommand cmd = conn.CreateCommand();
                        SqlDataAdapter da = new SqlDataAdapter(cmd);
                        cmd.CommandText = "SELECT TOP 1 * FROM SAP_Code WHERE CodeTypeId IS NULL;";
                        DataSet ds = new DataSet();
                        da.Fill(ds);
                        dt = ds.Tables[0];
                    }

                    // Write into dataTable
                    IRfcTable tbl = f.GetTable(i);
                    if (hasParentId1 && hasParentId2)
                    {
                        for (int rowIndex = 0; rowIndex < tbl.RowCount; rowIndex++)
                        {
                            DataRow newRow = dt.NewRow();
                            newRow["CodeTypeId"] = codeTypeId;
                            newRow["Id"] = tbl[rowIndex].GetValue(2);
                            newRow["DisplayText"] = tbl[rowIndex].GetValue(3);
                            newRow["DisplaySequence"] = (rowIndex + 1);
                            newRow["ParentId1"] = tbl[rowIndex].GetValue(0);
                            newRow["ParentId2"] = tbl[rowIndex].GetValue(1);
                            dt.Rows.Add(newRow);
                        }
                    }
                    else if (hasParentId1)
                    {
                        for (int rowIndex = 0; rowIndex < tbl.RowCount; rowIndex++)
                        {
                            DataRow newRow = dt.NewRow();
                            newRow["CodeTypeId"] = codeTypeId;
                            newRow["Id"] = tbl[rowIndex].GetValue(1);
                            newRow["DisplayText"] = tbl[rowIndex].GetValue(2);
                            newRow["DisplaySequence"] = (rowIndex + 1);
                            newRow["ParentId1"] = tbl[rowIndex].GetValue(0);
                            //newRow["ParentId2"] = tbl[rowIndex].GetValue(1);
                            dt.Rows.Add(newRow);
                        }
                    }
                    else
                    {
                        for (int rowIndex = 0; rowIndex < tbl.RowCount; rowIndex++)
                        {
                            DataRow newRow = dt.NewRow();
                            newRow["CodeTypeId"] = codeTypeId;
                            newRow["Id"] = tbl[rowIndex].GetValue(0);
                            newRow["DisplayText"] = tbl[rowIndex].GetValue(1);
                            newRow["DisplaySequence"] = (rowIndex + 1);
                            //newRow["ParentId1"] = tbl[rowIndex].GetValue(1);
                            //newRow["ParentId2"] = tbl[rowIndex].GetValue(1);
                            dt.Rows.Add(newRow);
                        }
                    }



                    break;
                } // if (metadata.DataType == RfcDataType.TABLE)
            } // for (int i = 0; i < f.ElementCount; i++)

            return dt;
        }

        /// <summary>
        /// This method will call a SAP function.
        /// It further assumes that the SAP will have a TABLE as part of its results.
        /// The method will grab the first table and return that as the resulting datatable.
        /// </summary>
        /// <param name="functionName">Name of the SAP function</param>
        /// <returns>A DataTable cast from the first TABLE result returned from the SAP function call</returns>
        public DataTable GetDataTableFromFunction(string functionName)
        {
            IRfcFunction sapRfcFunction = this.rfcDestination.Repository.CreateFunction(functionName);
            sapRfcFunction.Invoke(rfcDestination);
            return GetDataTable(sapRfcFunction);
        }

        public DataTable GetDataTableFromFunction(string functionName, string codeTypeId)
        {
            IRfcFunction sapRfcFunction = this.rfcDestination.Repository.CreateFunction(functionName);
            sapRfcFunction.Invoke(rfcDestination);
            return GetSapDataTable(sapRfcFunction, codeTypeId);
        }

        public DataTable GetDataTableFromFunction(string functionName, string codeTypeId, bool hasParentId1, bool hasParentId2)
        {
            IRfcFunction sapRfcFunction = this.rfcDestination.Repository.CreateFunction(functionName);
            sapRfcFunction.Invoke(rfcDestination);
            return GetSapDataTable(sapRfcFunction, codeTypeId, hasParentId1, hasParentId2);
        }

        #endregion Helper functions


        public DataTable GetSapQualification()
        {
            //IRfcFunction sapRfcFunction = this.rfcDestination.Repository.CreateFunction("Z_HR_QUALIFICATION_VALUES");
            //sapRfcFunction.Invoke(rfcDestination);
            //return GetDataTable(sapRfcFunction);

            return GetDataTableFromFunction("Z_HR_QUALIFICATION_VALUES");
        }


        #region reference code for study
        
        //public void AuthenticatePassword(string emp_code, string password)
        //{
        //    IRfcFunction loginFunc = this.rfcDestination.Repository.CreateFunction("Z_HR_AUTHENTICATE_PASSWORD");
        //    loginFunc.SetValue("IV_EMP_CODE", emp_code);
        //    loginFunc.SetValue("IV_PASSWORD", password);
        //    loginFunc.Invoke(rfcDestination);
        //    IRfcTable resultRfcTable = loginFunc.GetTable("RETURN");
        //    IRfcStructure rowRfcStructure = resultRfcTable.CurrentRow;
        //}

        //public void Log(IRfcFunction f)
        //{
        //    using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\Logs\\func.log", true))
        //    {
        //        sw.AutoFlush = true;
        //        sw.WriteLine("Element count: {0}", f.ElementCount);
        //        for (int i = 0; i < f.ElementCount; i++)
        //        {
        //            sw.WriteLine("Element metadata: {0}", f.GetElementMetadata(0));
        //        }
        //    }
        //}

        #endregion reference code for study
    }
}
